package com.zoho.daliansheng.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zoho.daliansheng.common.U8SystemRecord;
import com.zoho.daliansheng.common.ZohoRecord;
import com.zoho.daliansheng.config.CRMPathConfig;
import com.zoho.daliansheng.config.DatasourceEnum;
import com.zoho.daliansheng.config.U8SystemPathConfig;
import com.zoho.daliansheng.dlcr.DlcrU8WebService;
import com.zoho.daliansheng.dlcr.DlcrU8WebServiceSoap;
import com.zoho.daliansheng.dlcr.QueryRetInfo;
import com.zoho.daliansheng.utils.CommonUtil;
import com.zoho.daliansheng.utils.CrmApiUtil;
import com.zoho.daliansheng.utils.getCrmFieldUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CurrentStockServiceImpl implements CurrentStockService {

    ZohoRecord zohoRecord;

    U8SystemRecord u8SystemRecord;

    U8SystemPathConfig u8SystemPathConfig;

    CRMPathConfig crmPathConfig;

    public CurrentStockServiceImpl(ZohoRecord zohoRecord, U8SystemRecord u8SystemRecord, U8SystemPathConfig u8SystemPathConfig, CRMPathConfig crmPathConfig) {
        this.zohoRecord = zohoRecord;
        this.u8SystemRecord = u8SystemRecord;
        this.u8SystemPathConfig = u8SystemPathConfig;
        this.crmPathConfig = crmPathConfig;
    }

    @Override
    public void synCurrentStock() {
        /*
         * 1 获取CRM 现存量 模块数据
         */
        List<String> fieldList = getCrmFieldUtil.getCurrentStockFieldList();
        List<JSONObject> crmData = CrmApiUtil.getModuleData(zohoRecord.getAccessToken(), crmPathConfig.getCurrentStockModuleName(), fieldList);
        //System.out.println("crmData.size() = " + crmData.size());

        // 产品仓库
        List<String> tempFieldList = getCrmFieldUtil.getWarehouseFieldList();
        List<JSONObject> warehouseData = CrmApiUtil.getModuleData(zohoRecord.getAccessToken(), crmPathConfig.getWarehouseModuleName(), tempFieldList);

        // 产品
        List<String> productFieldList = getCrmFieldUtil.getProductFieldList();
        List<JSONObject> productData = CrmApiUtil.getModuleData(zohoRecord.getAccessToken(), crmPathConfig.getProductModuleName(), productFieldList);

        /*
         * 2 同步ERP 现存量
         */
        try {
//            synU8Data(crmData, DatasourceEnum.GONG_CHANG.getWebServiceUrl(), DatasourceEnum.GONG_CHANG.getAccountCode(), DatasourceEnum.GONG_CHANG.getCompanyName(), warehouseData, productData);
            synU8Data(crmData, DatasourceEnum.SU_ZHOU.getWebServiceUrl(), DatasourceEnum.SU_ZHOU.getAccountCode(), DatasourceEnum.SU_ZHOU.getCompanyName(), warehouseData, productData);
            synU8Data(crmData, DatasourceEnum.CHANG_ZHOU.getWebServiceUrl(), DatasourceEnum.CHANG_ZHOU.getAccountCode(), DatasourceEnum.CHANG_ZHOU.getCompanyName(), warehouseData, productData);
            synU8Data(crmData, DatasourceEnum.DA_LIAN.getWebServiceUrl(), DatasourceEnum.DA_LIAN.getAccountCode(), DatasourceEnum.DA_LIAN.getCompanyName(), warehouseData, productData);
            synU8Data(crmData, DatasourceEnum.XIN_CAI_LIAO.getWebServiceUrl(), DatasourceEnum.XIN_CAI_LIAO.getAccountCode(), DatasourceEnum.XIN_CAI_LIAO.getCompanyName(), warehouseData, productData);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    private void synU8Data(List<JSONObject> crmData, String webServiceUrl, String accountCode, String companyName,
                           List<JSONObject> warehouseData, List<JSONObject> productData) throws MalformedURLException {

        log.info("同步【" + companyName + "】");

        String synModuleName = crmPathConfig.getCurrentStockModuleName(); // 要同步的模块名称

        // 1 过滤CRM数据，只保留单一账套
        crmData = crmData.stream().filter(object -> Objects.nonNull(object.getString("AffiliatedCompany")) && object.getString("AffiliatedCompany").equals(companyName)).collect(Collectors.toList());

        // 2 模块最大版本号
        Map<String, String> map = CrmApiUtil.getMaxVersion(zohoRecord.getAccessToken(), synModuleName, accountCode);
        String versionCrmId = map.get("id");
        int maxVersion = Integer.parseInt(map.get("maxVersion"));

        // 3 获取ERP数据
        DlcrU8WebService webService = new DlcrU8WebService(new URL(webServiceUrl));
        DlcrU8WebServiceSoap api = webService.getDlcrU8WebServiceSoap();
        QueryRetInfo queryRetInfo = api.queryCurrentStockByVersion(maxVersion);
        int queryMaxVersion = queryRetInfo.getMaxVersion();
        JSONArray jsonArray = JSONArray.parseArray(queryRetInfo.getJson());
        if (jsonArray.size() > 0) {
            // 4 比较数据
            List<JSONObject> insertList = new ArrayList<>();
            List<JSONObject> updateList = new ArrayList<>();
            List<String> deleteList = new ArrayList<>();
            List<JSONObject> batchCurrentStock = jsonArray.toJavaList(JSONObject.class);

            if (maxVersion == -1) {
                if (crmData.size() == 0) {
                    insertList = batchCurrentStock;
                } else {
                    for (JSONObject erpData : batchCurrentStock) {
                        String autoid = erpData.getString("autoid"); // erp id
                        List<JSONObject> searchList = crmData.stream().filter(object ->
                                Objects.nonNull(object.getString("autoid")) && object.getString("autoid").equals(autoid) &&
                                        Objects.nonNull(object.getString("AffiliatedCompany")) && object.getString("AffiliatedCompany").equals(companyName)
                        ).collect(Collectors.toList());
                        if (searchList.size() > 0) {
                            JSONObject jsonObject = searchList.get(0);
                            String crmId = jsonObject.getString("id");
                            erpData.put("crmId", crmId);
                            updateList.add(erpData);
                        } else {
                            insertList.add(erpData);
                        }
                    }
                }
            } else {
                for (JSONObject erpData : batchCurrentStock) {
                    // sys_change_operation 该字段非常关键,记录了记录的变动类型,I=Insert、U=Update、D=Delete
                    String operation = erpData.getString("sys_change_operation");
                    String autoid = erpData.getString("autoid"); // erp id
                    List<JSONObject> searchList = crmData.stream().filter(object ->
                            Objects.nonNull(object.getString("autoid")) && object.getString("autoid").equals(autoid) &&
                                    Objects.nonNull(object.getString("AffiliatedCompany")) && object.getString("AffiliatedCompany").equals(companyName)
                    ).collect(Collectors.toList());

                    if ("I".equals(operation)) {
                        insertList.add(erpData);
                    } else if ("U".equals(operation)) {
                        if (searchList.size() > 0) {
                            JSONObject jsonObject = searchList.get(0);
                            String crmId = jsonObject.getString("id");
                            erpData.put("crmId", crmId);
                            updateList.add(erpData);
                        }
                    } else if ("D".equals(operation)) {
                        if (searchList.size() > 0) {
                            JSONObject jsonObject = searchList.get(0);
                            String crmId = jsonObject.getString("id");
                            deleteList.add(crmId);
                        }
                    }
                }
            }

            // 5 字段映射
            List<JSONObject> crm_insertList = getCrmMappingData(insertList, companyName, warehouseData, productData, accountCode);
            List<JSONObject> crm_updateList = getCrmMappingData(updateList, companyName, warehouseData, productData, accountCode);

            System.out.println("crm_insertList.size() = " + crm_insertList.size());
            System.out.println("crm_updateList.size() = " + crm_updateList.size());
            System.out.println("deleteList.size() = " + deleteList.size());

            // 6 批量操作
            CrmApiUtil.batchInsertDataByList(zohoRecord.getAccessToken(), crm_insertList, synModuleName);
            CrmApiUtil.batchUpdateDataByList(zohoRecord.getAccessToken(), crm_updateList, synModuleName);
            if (!deleteList.isEmpty()) {
                CrmApiUtil.batchDeleteModelData(zohoRecord.getAccessToken(), synModuleName, deleteList);
            }

            // 7 最大版本号回传
            if (queryMaxVersion != maxVersion) {
                CrmApiUtil.saveMaxVersion(zohoRecord.getAccessToken(), versionCrmId, queryMaxVersion, crmPathConfig.getMaxVersionModuleName());
            }
        }
    }

    private List<JSONObject> getCrmMappingData(List<JSONObject> erpList, String companyName, List<JSONObject> warehouseData, List<JSONObject> productData, String accountCode) {

        List<JSONObject> list = new ArrayList<>();
        for (JSONObject erpData : erpList) {
            JSONObject crmData = new JSONObject();
            String crmId = erpData.getString("crmId");
            if (StringUtils.isNotBlank(crmId)) {
                crmData.put("id", crmId);
            }
            crmData.put("AffiliatedCompany", companyName); // 所属公司

            if (StringUtils.isBlank(erpData.getString("cbatch"))) {
                continue;
            } else {
                crmData.put("Name", erpData.getString("cbatch")); // 批号
            }

            String whcode = erpData.getString("cwhcode"); // 仓库编码
            if (StringUtils.isNotBlank(whcode)) {
                JSONObject wharehouse = getWharehouse(whcode, warehouseData, companyName);
                if (Objects.nonNull(wharehouse)) {
                    crmData.put("whname", wharehouse); // 仓库名称
                }
            }

            String invcode = erpData.getString("cinvcode");  // 存货编码
            crmData.put("invcode", invcode); // 存货编码
            if (StringUtils.isNotBlank(invcode)) {
                JSONObject product = getProduct(invcode, productData, accountCode, companyName);
                if (Objects.nonNull(product)) {
                    product.remove("changerate");
                    crmData.put("invname", product); // 存货名称
                }
            }

            crmData.put("autoid", erpData.getString("autoid")); // erp id
            crmData.put("sys_change_version", erpData.getString("sys_change_version")); // 当前数据版本号
            crmData.put("SpecificationModel", erpData.getString("cinvstd")); // 规格型号
            crmData.put("DangerousGoodsAndGeneralCargo", erpData.getString("cinvdefine4")); // 危货普货
            crmData.put("invdefine", erpData.getString("cinvdefine7")); // 产品供货商

            BigDecimal qty = erpData.getBigDecimal("iquantity");
            BigDecimal inum = erpData.getBigDecimal("inum");
            crmData.put("exist_availqty", CommonUtil.formatBigDecimal(qty, 5)); // 现存数量
            crmData.put("exist_num", CommonUtil.formatBigDecimal(inum, 3)); // 现存件数

            BigDecimal transinqty = erpData.getBigDecimal("ftransinquantity");
            BigDecimal ftransinnum = erpData.getBigDecimal("ftransinnum");
            crmData.put("transfers_availqty", CommonUtil.formatBigDecimal(transinqty, 5)); // 调拨在途数量
            crmData.put("transfers_num", CommonUtil.formatBigDecimal(ftransinnum, 3)); // 调拨在途件数

            BigDecimal inqtysum = erpData.getBigDecimal("finquantity");
            BigDecimal finnum = erpData.getBigDecimal("finnum");
            crmData.put("storage_total_availqty", CommonUtil.formatBigDecimal(inqtysum, 5)); // 预计入库数量合计
            crmData.put("storage_total_num", CommonUtil.formatBigDecimal(finnum, 3)); // 预计入库件数合计

            BigDecimal availqty = erpData.getBigDecimal("favaqty");
            BigDecimal favanum = erpData.getBigDecimal("favanum");
            crmData.put("availqty", CommonUtil.formatBigDecimal(availqty, 5)); // 可用数量
            crmData.put("available_num", CommonUtil.formatBigDecimal(favanum, 3)); // 可用件数

            crmData.put("good_ship_availqty", erpData.getString("foutquantity")); // 待发货数量
            crmData.put("good_ship_num", erpData.getString("foutnum")); // 待发货件数

            crmData.put("Production_date", CommonUtil.formatTime(erpData.getString("dmdate"))); // 生产日期
            crmData.put("massdate", erpData.getString("imassdate")); // 保质期
            crmData.put("vdate", CommonUtil.formatTime(erpData.getString("dvdate"))); // 失效日期
            crmData.put("cAddress", erpData.getString("caddress")); // 产地/厂牌
            crmData.put("cCurrencyName", erpData.getString("cCurrencyName")); // 通用名称
            crmData.put("cEnterprise", erpData.getString("cEnterprise")); //  生产企业
            list.add(crmData);
        }
        return list;
    }

    // 获取产品仓库
    private JSONObject getWharehouse(String code, List<JSONObject> warehouseData, String companyName) {
        List<JSONObject> list = warehouseData.stream().filter(object ->
                object.getString("warehouse_code").equals(code) && object.getString("AffiliatedCompany").equals(companyName)
        ).collect(Collectors.toList());
        if (list.size() > 0) {
            String houseId = list.get(0).getString("id");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", houseId);
            return jsonObject;
        }
        return null;
    }

    // 获取产品
    private JSONObject getProduct(String code, List<JSONObject> productData, String accountCode, String companyName) {
        List<JSONObject> list = productData.stream().filter(object ->
                Objects.nonNull(object.getString("Product_Code")) && object.getString("Product_Code").equals(code)
                        && object.getString("AffiliatedCompany").equals(companyName)
        ).collect(Collectors.toList());
        if (list.size() == 1) {
            String productId = list.get(0).getString("id");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", productId);
            jsonObject.put("changerate", list.get(0).getBigDecimal("changerate"));
            return jsonObject;
        } else if (list.size() > 1) {
            for (JSONObject jsonObject : list) {
                String affiliatedCompany = jsonObject.getString("AffiliatedCompany");
                String transferDataSource = CommonUtil.getdataSourceByName(affiliatedCompany);
                if (transferDataSource.equals(accountCode)) {
                    String productId = jsonObject.getString("id");
                    JSONObject tempJson = new JSONObject();
                    tempJson.put("id", productId);
                    tempJson.put("changerate", jsonObject.getBigDecimal("changerate"));
                    return tempJson;
                }
            }
        }
        return null;
    }

    // 件数  = 数量 / 换算率，保留3位
    private BigDecimal transferMount(BigDecimal num, BigDecimal changerate) {
        if (Objects.nonNull(changerate) && !changerate.equals(BigDecimal.ZERO)) {
            return num.divide(changerate, 3);
        }
        return new BigDecimal(0);
    }

}
